package cn.cxj.user.service.impl;

import cn.cxj.basic.constant.WxConstants;
import cn.cxj.basic.exception.BusinessException;
import cn.cxj.basic.util.AjaxResult;
import cn.cxj.basic.util.HttpClientUtils;
import cn.cxj.basic.util.MD5Utils;
import cn.cxj.user.domain.Logininfo;
import cn.cxj.user.domain.User;
import cn.cxj.user.domain.WxUser;
import cn.cxj.user.dto.LoginDto;
import cn.cxj.user.mapper.LogininfoMapper;
import cn.cxj.user.mapper.UserMapper;
import cn.cxj.user.mapper.WxUserMapper;
import cn.cxj.user.service.ILoginService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author chenxinjie
 * @date 2022-2-7 22:48:59
 */
@Service
public class LoginServiceImpl implements ILoginService {
    
    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private UserMapper userMapper;
    
    @Override
    public Map<String, Object> accountLogin(LoginDto dto) {
        // 校验
        if (dto == null) {
            throw new BusinessException("账号或者密码不能为空!");
        }
        // 校验type
        if (dto.getType() == null) {
            throw new BusinessException("一定要传type!");
        }
        // 根据username查询数据库t_employee
        Logininfo logininfo = logininfoMapper.loadByUsername(dto);
        if (logininfo == null) {
            throw new BusinessException("用户名不存在!");
        }
        // 跟数据库中密码进行比对
        String salt = logininfo.getSalt();
        String md5Pwd = MD5Utils.encrypByMd5(dto.getPassword() + salt);
        if (!logininfo.getPassword().equals(md5Pwd)) {
            throw new BusinessException("密码错误!");
        }
        // 登陆成功
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(
                token,
                // 对象存入redis需要序列化,实现serializable接口
                logininfo,
                30,
                TimeUnit.MINUTES
                );
        // 返回登陆成功的必要信息
        Map<String, Object> map = new HashMap<>();
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        map.put("token", token);
        map.put("logininfo", logininfo);
        return map;
    }

    @Override
    public AjaxResult wechat(String code) {
        // 校验参数不能为空
        if (StringUtils.isEmpty(code)) {
            throw new BusinessException("参数不能为空!");
        }
        String tokenTemp = HttpClientUtils.httpGet(WxConstants.GET_ACK_URL
                .replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code));
        System.out.println(tokenTemp);
        // 使用fastjson将字符串转换为key->value的格式方便使用
        JSONObject jsonObject = JSON.parseObject(tokenTemp);
        String openid = jsonObject.getString("openid");
        String accessToken = jsonObject.getString("access_token");
        // 根据token里面的openid查询t_wxuser表
        WxUser wxUser = wxUserMapper.loadByOpenId(openid);
        // 如果wxUser不为空说明是老用户
        if(wxUser != null && wxUser.getUser_id() != null){
            // 根据wxUser的user_id查询t_user
            User user = userMapper.loadById(wxUser.getUser_id());
            // 根据User的logininifo_id查询t_logininfo
            Logininfo logininfo = logininfoMapper.loadById(user.getLogininfo_id());
            // 免密登陆
            String token = UUID.randomUUID().toString();
            redisTemplate.opsForValue().set(
                    token,
                    // 对象存入redis需要序列化,实现serializable接口
                    logininfo,
                    30,
                    TimeUnit.MINUTES
            );
            // 返回登陆成功的必要信息
            Map<String, Object> map = new HashMap<>();
            logininfo.setSalt(null);
            logininfo.setPassword(null);
            map.put("token", token);
            map.put("logininfo", logininfo);
            return AjaxResult.me().setResultObj(map);
        }else{
            // 新用户跳转到绑定手机号界面,携带openid和access_token
            String url = "/binder.html?openid=" + openid + "&access_token=" + accessToken ;
            return AjaxResult.me().setSuccess(false).setResultObj(url);
        }
    }

    @Override
    public AjaxResult binder(Map<String, String> paramas) {
        // 获取前端传过来的数据
        String phone = paramas.get("phone");
        String verifyCode = paramas.get("verifyCode");
        String openid = paramas.get("openid");
        String access_token = paramas.get("access_token");
        System.out.println(access_token);
        System.out.println(openid);
        // 准备wxUser所需要的对象信息
        String result = HttpClientUtils.httpGet(WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", access_token))
                .replace("OPENID", openid);
        System.out.println(result);
        JSONObject jsonObject = JSON.parseObject(result);
        WxUser wxUser = new WxUser();
        wxUser.setOpenid(jsonObject.getString("openid"));
        wxUser.setNickname(jsonObject.getString("nickname"));
        wxUser.setUnionid(jsonObject.getString("unionid"));
        wxUser.setSex(jsonObject.getInteger("sex"));
        wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
        // 基于手机号查询t_user
        User user = userMapper.loadByPhone(phone);
        Logininfo logininfo = null;
        if (user == null) {
            // 如果查询不到说明是新用户
            // 先生成一个User对象再生成对应的Logininfo
            user = new User();
            user.setPhone(phone);
            user.setUsername("p_"+phone);
            user.setCreatetime(new Date());
            user.setState(1);
            logininfo = user2Logininfo(user);
            logininfoMapper.save(logininfo);
            user.setLogininfo_id(logininfo.getId());
            userMapper.save(user);
        }
        // 如果有值,说明该用户已经使用手机号注册过该网站
        // 生成一个wxUser对象和该User进行绑定
        wxUser.setUser_id(user.getId());
        wxUserMapper.save(wxUser);
        // 免密登陆
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(
                token,
                // 对象存入redis需要序列化,实现serializable接口
                logininfo,
                30,
                TimeUnit.MINUTES
        );
        // 返回登陆成功的必要信息
        Map<String, Object> map = new HashMap<>();
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        map.put("token", token);
        map.put("logininfo", logininfo);
        return AjaxResult.me().setResultObj(map);
    }

    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        // 同名原则拷贝
        BeanUtils.copyProperties(user, logininfo);
        logininfo.setType(1);
        return logininfo;
    }
}